unit RclClasses;

interface

uses
  Windows, Classes,
  RclLog, LogLab;

type
  TRclInterfacedObject = class(TObject, IInterface)
  private
    FRefCount: Integer;
  protected
    FOwner: Boolean;
  public
    { IInterface }
    function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

    constructor Create(Owner: Boolean); overload;
    constructor Create; overload; virtual;
  end;

  TRclInterfacedPersistent = class(TPersistent, IInterface)
  private
    FRefCount: Integer;
    FClassName: string;
  protected
    FOwner: Boolean;
  public
    { IInterface }
    function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

    constructor Create(Owner: Boolean); overload;
    constructor Create; overload; virtual;
  end;

  TRclInterfacedPersistentClass = class of TRclInterfacedPersistent;

  TRclObject = class(TRclInterfacedPersistent)
  protected
    log: ILog;
    destructor Destroy; override;
  public
    constructor Create; override;

    function toString: string; virtual;
  end;

  TRclObjectClass = class of TRclObject;

  TRclClassUtils = class(TObject)
  public
    class procedure GetIntf(AObj: TObject; const AIID: TGUID; out obj);
  end;

implementation

{ TRclObject }

constructor TRclObject.Create;
begin
  inherited Create;
  log := RclLog.GetLogVendor.GetLog(Self);
end;

destructor TRclObject.Destroy;
begin  
  inherited;
end;

function TRclObject.toString: string;
begin
  Result := Self.ClassName;
end;

{ TBaClassUtils }

class procedure TRclClassUtils.GetIntf(AObj: TObject; const AIID: TGUID; out
    obj);
begin
  if AObj = nil then Exit;
  AObj.GetInterface(AIID, obj);
end;

{ TRclInterfacedObject }

constructor TRclInterfacedObject.Create(Owner: Boolean);
begin
  FOwner := Owner;
end;

constructor TRclInterfacedObject.Create;
begin
  Create(False);
end;

function TRclInterfacedObject.QueryInterface(const IID: TGUID;
  out Obj): HResult;
const
  E_NOINTERFACE = HResult($80004002);
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

function TRclInterfacedObject._AddRef: Integer;
begin
  Result := InterlockedIncrement(FRefCount)
end;

function TRclInterfacedObject._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    if FOwner then
      Destroy;
end;

{ TRclInterfacedPersistent }

constructor TRclInterfacedPersistent.Create(Owner: Boolean);
begin
  FOwner := Owner;
  FRefCount := 0;
  FClassName := Self.ClassName;
end;

constructor TRclInterfacedPersistent.Create;
begin
  Create(False);  
end;

function TRclInterfacedPersistent.QueryInterface(const IID: TGUID;
  out Obj): HResult;
const
  E_NOINTERFACE = HResult($80004002);
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

function TRclInterfacedPersistent._AddRef: Integer;
begin
  Result := InterlockedIncrement(FRefCount);
end;

function TRclInterfacedPersistent._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    if FOwner then
      Destroy;
end;

end.
